package cc.yihy.util.tree;

import cc.yihy.util.tree.bean.Tree;
import cc.yihy.util.tree.bean.TreeNode;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @author Yihy
 * @version V1.0
 * @Package cc.yihy.util
 * @Description:
 * @date 2017/6/8 10:38
 */
public class TreeUtils<K, V> {

    private Setting setting;

    private Map<K, TreeNode<K, V>> result;

    private Set<TreeNode<K, V>> treeNodeTopSet;


    public TreeUtils(Setting setting) {
        this.setting = setting;
    }

    public TreeUtils<K, V> load(List<V> list) throws ReflectiveOperationException {

        this.result = new HashMap<>(list.size());
        this.treeNodeTopSet = new HashSet<>();
        setTreeMap(list);

        creatTree(list);

        return this;
    }

    public Tree<K, V> build() {

        Tree<K, V> tTree = new Tree<>(result, treeNodeTopSet);

        result = null;
        treeNodeTopSet = null;
        setting = null;
        return tTree;
    }


    /**
     * 创建文章类型树和一级类型
     *
     * @param list
     */
    private void creatTree(List<V> list) throws ReflectiveOperationException {
        if (list == null || list.isEmpty()) return;

        for (V t : list) {

            //获取当前对象的父级key值
            Object parentKey = getParentName(t);

            //获取当前对象Tree对象
            Object key = getKey(t);
            TreeNode<K, V> treeNode = result.get(key);

            //父级key存在
            if (parentKey != null && !"".equals(parentKey) && !"0".equals(parentKey)) {

                //父级包装对象
                TreeNode<K, V> parent = result.get(parentKey);

                if (parent != null) {
                    //增加当前对象的父级
                    treeNode.setParent(parent);
                    //增加父级对象的子级
                    parent.getChildren().add(treeNode);
                }


                //父级key不存在，即最上级
            } else {

                treeNodeTopSet.add(treeNode);
            }


        }

    }

    /**
     * 初始化列表集合
     *
     * @param list
     * @throws Exception
     */
    private void setTreeMap(List<V> list) throws ReflectiveOperationException {
        if (list == null || list.isEmpty()) return;
        for (V t : list) {
            K key = getKey(t);
            this.result.put(key, new TreeNode(key, t));
        }
    }


    private K getKey(V t) throws ReflectiveOperationException {
        Method keyMethod = setting.getBeanClass().getDeclaredMethod(getMethodStr(setting.getKeyName()));
        K value = (K) keyMethod.invoke(t);

        return value;
    }

    private K getParentName(V t) throws ReflectiveOperationException {
        Method keyMethod = setting.getBeanClass().getDeclaredMethod(getMethodStr(setting.getParentName()));
        K value = (K) keyMethod.invoke(t);

        return value;
    }

    private String getMethodStr(String str) {
        return "get" + str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
    }
}
